<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title></title>
    <!-- 这里可以添加CSS样式文件 -->
  </head>
  <body>
     <script type="importmap">
      {
        "imports": {
          "three": "./threejs/build/three.module.js",
          "three/addons/": "./threejs/examples/jsm/"
        }
      }
    </script>
    <script type="module">
      import * as THREE from "three";
      import { OrbitControls } from "three/addons/controls/OrbitControls.js";
      import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
      import { DRACOLoader } from "three/addons/loaders/DRACOLoader.js";

      

      const scene = new THREE.Scene();

      const camera = new THREE.PerspectiveCamera(
        75,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
      );

      camera.position.set(3, 3, 3);

      const renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true,
        logarithmicDepthBuffer: true,
      });

      renderer.setSize(window.innerWidth, window.innerHeight);

      document.body.appendChild(renderer.domElement);

      new OrbitControls(camera, renderer.domElement);

      window.onresize = () => {
        renderer.setSize(window.innerWidth, window.innerHeight);

        camera.aspect = window.innerWidth / window.innerHeight;

        camera.updateProjectionMatrix();
      };

      scene.add(new THREE.AmbientLight(0xffffff, 3));

      scene.add(new THREE.AxesHelper(1000));

      let car = null;

      const loader = new GLTFLoader();

      loader.setDRACOLoader(
        new DRACOLoader().setDecoderPath(
          "./js/three/draco/"
        )
      );

      loader.load(
        "/files/model/car.glb",

        (gltf) => {
          car = gltf.scene;

          scene.add(car);

          modelBlendShader(car, document.body);
        }
      );

      animate();

      function animate() {
        requestAnimationFrame(animate);

        car?.render?.();

        renderer.render(scene, camera);
      }

      /* 混合着色 */
      function modelBlendShader(model, DOM) {
        let materials = [];

        model.traverse((c) => c.isMesh && materials.push(c.material));

        materials = [...new Set(materials)];

        const uniforms = {
          iResolution: {
            type: "v2",
            value: new THREE.Vector2(window.innerWidth,window.innerHeight),
          },

          iTime: {
            type: "f",
            value: 1.0,
          },
        };

        materials.forEach((material) => {
          material.onBeforeCompile = (shader) => {
            shader.uniforms.iResolution = uniforms.iResolution;

            shader.uniforms.iTime = uniforms.iTime;

            shader.fragmentShader = shader.fragmentShader.replace(
              /#include <common>/,
              `
                uniform vec2 iResolution;
                uniform float iTime;
                #include <common> 
            `
            );

            shader.fragmentShader = shader.fragmentShader.replace(
              "vec4 diffuseColor = vec4( diffuse, opacity );",
              `
                vec3 c;
                float l,z=iTime;
                for(int i=0;i<3;i++) {
                    vec2 uv,p=gl_FragCoord.xy/iResolution/2.0;
                    uv=p +  2.0;
                    p-=.5;
                    p.x*=iResolution.x/iResolution.y;
                    z+=.07;
                    l=length(p);
                    uv+=p/l*(sin(z)+1.)*abs(sin(l*9.-z-z));
                    c[i]=.01/length(mod(uv,1.)-.5);
                }
                vec4 diffuseColor = vec4( diffuse * c  * vec3(20.,20.,20.), opacity );
            `
            );
          };

          material.needsUpdate = true;
        });

        model.render = () => (uniforms.iTime.value += 0.02);
      }
    </script>
  </body>
</html>
